/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * assign2
 * Copyright (C)  Michael Morckos 2008 <mikey.morckos@gmail.com>
 * 
 * assign2 is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * assign2 is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "plotter.h"

#include <gtkmm/main.h>
#include <gtkmm/window.h>
#include <cairomm/context.h>
#include <iostream>

using namespace std;

Graph_Plotter :: Graph_Plotter(Intensity* RED, Intensity* GREEN, Intensity* BLUE) {
    
	R = RED;
	G = GREEN;
	B = BLUE;
	type = 0;
	
	all = TRUE;
}

Graph_Plotter :: Graph_Plotter(Intensity* SINGLE, int index) {
    
	S = SINGLE;
	all = FALSE;
	type = 0;
	
	this->index = index;
}

Graph_Plotter :: Graph_Plotter() {}

Graph_Plotter :: ~Graph_Plotter() {}

void Graph_Plotter :: setType(int i) {
	
	type = i;
}	

bool Graph_Plotter :: on_expose_event(GdkEventExpose* event) {
	
  // This is where we draw on the window
	Glib::RefPtr<Gdk::Window> window = get_window();
    
	if(window) {
		Gtk::Allocation allocation = get_allocation();
        int width = allocation.get_width();
        int height = allocation.get_height();
	    int origin = 40;
		int offset = width / 6;
	
        height-= origin;
		width -= origin;
		
        Cairo :: RefPtr<Cairo :: Context> cr = window->create_cairo_context();
        cr->set_line_width(3.0);

        cr->rectangle(event->area.x, event->area.y, event->area.width, event->area.height);
        cr->clip();

	    cr->set_source_rgb(0.0, 0.0, 0.0);
	    cr->move_to(40, height);
	    cr->line_to(width, height);
	    cr->move_to(40, height);
	    cr->line_to(40, 40);
	    cr->stroke();
	  
	    cr->move_to(40, height);
	    cr->set_source_rgb(0.0, 0.0, 0.0);
	    cr->set_line_width(0.8);
		
		/* X-AXIS */
		for(int i = origin; i < width; i+= offset) {
			if(i != origin) {
		        cr->move_to(i, height + 5);
		        cr->line_to(i, height - 5);
			}	
		}		
		/* Y-AXIS */
	    for (int i = height - 50; i >= origin; i-=50) {
			if(i >= 40) {
			   cr->move_to(35, i);
		       cr->line_to(45, i);
			}	
            cr->stroke();
        }
		
		/* Plotting the graphs */
		int val, ampl;
		if(all) {
			Intensity* temp = R, *temp2 = G, *temp3 = B;
			//cout << "Type " << type << endl;
			if(type == 0) {
				/* RED */
				for(int i = 0; i < 254; i++) {
			        val = temp->getVal(); 
			        ampl = temp->getAmpl();
			
			        cr->set_source_rgb(1.0, 0.0, 0.0);
			        cr->move_to((4 * val) + 40, height);
			        cr->line_to((4 * val) + 40, (height - ampl));
			        cr->stroke();
			
	     		    temp++;
		        }
		        /* GREEN */
		        for(int i = 0; i < 256; i++) {
			        val = temp2->getVal(); 
			        ampl = temp2->getAmpl();
			
			        cr->set_source_rgb(0.0, 1.0, 0.0);
			        cr->move_to((4 * val) + 40, height);
			        cr->line_to((4 * val) + 40, (height - ampl));
			        cr->stroke();
			
			        temp2++;
		        }
		        /* BLUE */
		        for(int i = 0; i < 256; i++) {
			        val = temp3->getVal(); 
			        ampl = temp3->getAmpl();
			
			        cr->set_source_rgb(0.0, 0.0, 1.0);
			        cr->move_to((4 * val) + 40, height);
			        cr->line_to((4 * val) + 40, (height - ampl));
			        cr->stroke();
			
		    	    temp3++;
		        }
			}
			/* CUMULATIVE */
			else {
				/* RED */
				int cummu = temp->getAmpl(); int val2, ampl2;
				cr->set_source_rgb(1.0, 0.0, 0.0);
				for(int i = 0; i < 254; i++) {
			        val = temp->getVal(); 
			        ampl = temp->getAmpl();
					
					while(ampl > 500) 
						ampl -= 500;
					
					if(ampl > 100)
						ampl = ampl/100;
					else
						ampl = ampl/10;
			
			        cr->set_source_rgb(1.0, 0.0, 0.0);
			        cr->move_to((4 * val) + 40, (height - cummu));
					
					temp++;
					val2 = temp->getVal();
					ampl2 = temp->getAmpl();
					
					while(ampl2 > 500) 
						ampl2 -= 500;
					
					if(ampl2 > 100)
						ampl2 = ampl2/100;
					else
						ampl2 = ampl2/10;
					
					cummu += ampl2;
					
					cr->line_to((4 * val2) + 40, (height - cummu));
					
			        cr->stroke();
		        }
				/* GREEN */
				cummu = temp2->getAmpl();
				cr->set_source_rgb(0.0, 1.0, 0.0);
				for(int i = 0; i < 254; i++) {
					
			        val = temp2->getVal(); 
			        ampl = temp2->getAmpl();
					
					while(ampl > 500)
						ampl -= 500;
					
					if(ampl > 100)
						ampl = ampl/100;
					else
						ampl = ampl/10;
			
			        cr->set_source_rgb(0.0, 1.0, 0.0);
			        cr->move_to((4 * val) + 40, (height - cummu));
					
					temp2++;
					val2 = temp2->getVal();
					ampl2 = temp2->getAmpl();
					
					while(ampl2 > 500)
						ampl2 -= 500;
					
					if(ampl2 > 100)
						ampl2 = ampl2/100;
					else
						ampl2 = ampl2/10;
					
					cummu += ampl2;
					
					cr->line_to((4 * val2) + 40, (height - cummu));
					
			        cr->stroke();
		        }
				/* BLUE */
				cummu = temp3->getAmpl();
				
				while(cummu > 500)
						cummu -= 500;
					
					if(cummu > 100)
						cummu = ampl/100;
					else
						cummu = ampl/10;

				cr->set_source_rgb(0.0, 0.0, 1.0);
				for(int i = 0; i < 254; i++) {
			        val = temp3->getVal(); 
			        ampl = temp3->getAmpl();
					
					while(ampl > 500)
						ampl -= 500;
					
					if(ampl > 100)
						ampl = ampl/100;
					else
						ampl = ampl/10;
			
			        cr->set_source_rgb(0.0, 0.0, 1.0);
			        cr->move_to((4 * val) + 40, (height - cummu));
					
					temp3++;
					val2 = temp3->getVal();
					ampl2 = temp3->getAmpl();
					
					while(ampl2 > 500)
						ampl2 -= 500;
					
					if(ampl2 > 100)
						ampl2 = ampl2/100;
					else
						ampl2 = ampl2/10;
					
					cummu += ampl2;
					
					cr->line_to((4 * val2) + 40, (height - cummu));
					
			        cr->stroke();
		        }
			}	
		}
		/* SINGLE CHANNEL */
		else {
			Intensity* temp = S;
			switch(index) {
				case 0 :  cr->set_source_rgb(1.0, 0.0, 0.0); break;
				case 1 :  cr->set_source_rgb(0.0, 1.0, 0.0); break;
				case 2 :  cr->set_source_rgb(0.0, 0.0, 1.0); break;
				default : cr->set_source_rgb(0.0, 0.0, 0.0); break;
			}
			if(type == 0) {
				for(int i = 0; i < 256; i++) {
			        val = temp->getVal(); 
			        ampl = temp->getAmpl();
			
		    	    cr->move_to((4 * val) + 40, height);
		    	    cr->line_to((4 * val) + 40, (height - ampl));
			        cr->stroke();
			
		    	    temp++;
		        }
			}
			/* CUMULATIVE */
			else {
				int cummu = temp->getAmpl(); int val2, ampl2;
				
				for(int i = 0; i < 254; i++) {
			        val = temp->getVal(); 
			        ampl = temp->getAmpl();
					
					while(ampl > 500) 
						ampl -= 500;
					
					if(ampl > 100)
						ampl = ampl/100;
					else
						ampl = ampl/10;
			
			     //   cr->set_source_rgb(1.0, 0.0, 0.0);
			        cr->move_to((4 * val) + 40, (height - cummu));
					
					temp++;
					val2 = temp->getVal();
					ampl2 = temp->getAmpl();
					
					while(ampl2 > 500) 
						ampl2 -= 500;
					
					if(ampl2 > 100)
						ampl2 = ampl2/100;
					else
						ampl2 = ampl2/10;
					
					cummu += ampl2;
					
					cr->line_to((4 * val2) + 40, (height - cummu));
					
			        cr->stroke();
		        }
			}	
		}	
	    cr->stroke();
  }

  return true;
}

